from typing import overload, Literal, TypeVar, Tuple, Iterable

Bigs = TypeVar('Bigs', UBig, IBig, FBig, DBig, RBig)
SignedBigs = TypeVar('SignedBigs', IBig, FBig, DBig, RBig)

class Words:
    def __init__(self, obj: list[int] | Words): ...
    def __repr__(self) -> str: ...
    def __len__(self) -> int: ...
    @overload
    def __getitem__(self, index: int) -> int: ...
    @overload
    def __getitem__(self, index: slice) -> Words: ...
    @overload
    def __setitem__(self, index: int, value: int): ...
    @overload
    def __setitem__(self, index: slice, value: list[int] | Words): ...
    def __delitem__(self, index: int | slice): ...
    def __add__(self, other: list[int] | Words) -> Words: ...
    def __mul__(self, count: int) -> Words: ...

class UBig:
    def __init__(self, obj: int | str): ...
    def unwrap(self) -> int: ...
    def __repr__(self) -> str: ...
    def __str__(self) -> str: ...
    def __format__(self) -> str: ...
    def __hash__(self) -> int: ...

    def __len__(self) -> int: ...
    @overload
    def __getitem__(self, index: int) -> bool: ...
    @overload
    def __getitem__(self, index: slice) -> UBig: ...
    def __setitem__(self, index: int | slice, value: bool): ...
    def __delitem__(self, index: int, slice): ...

    def __int__(self) -> int: ...
    def to_words(self) -> Words: ...
    @staticmethod
    def from_words(words: Words) -> UBig: ...
    def to_chunks(self, chunk_bits: int) -> Tuple[UBig]: ...
    @staticmethod
    def from_chunks(chunks: Iterable[UBig], chunk_bits: int) -> UBig: ...
    def to_bytes(self, byteorder: Literal['little', 'big'] | None) -> bytes: ...
    @staticmethod
    def from_words(bytes: bytes, byteorder: Literal['little', 'big'] | None) -> UBig: ...

    @overload
    def __add__(self, other: Bigs) -> Bigs: ...
    @overload
    def __add__(self, other: int) -> IBig: ...
    @overload
    def __radd__(self, other: Bigs) -> Bigs: ...
    @overload
    def __radd__(self, other: int) -> IBig: ...
    @overload
    def __sub__(self, other: Bigs) -> Bigs: ...
    @overload
    def __sub__(self, other: int) -> IBig: ...
    @overload
    def __rsub__(self, other: Bigs) -> Bigs: ...
    @overload
    def __rsub__(self, other: int) -> IBig: ...
    @overload
    def __mul__(self, other: Bigs) -> Bigs: ...
    @overload
    def __mul__(self, other: int) -> IBig: ...
    @overload
    def __rmul__(self, other: Bigs) -> Bigs: ...
    @overload
    def __rmul__(self, other: int) -> IBig: ...
    @overload
    def __truediv__(self, other: Bigs) -> Bigs: ...
    @overload
    def __truediv__(self, other: int) -> IBig: ...
    @overload
    def __rtruediv__(self, other: Bigs) -> Bigs: ...
    @overload
    def __rtruediv__(self, other: int) -> IBig: ...
    def __mod__(self, other: int | UBig | IBig) -> UBig: ...
    def __pow__(self, exp: int | UBig, modulus: int | UBig | None) -> UBig: ...
    def __pos__(self) -> UBig: ...
    def __neg__(self) -> IBig: ...
    def __abs__(self) -> IBig: ...
    def __nonzero__(self) -> bool: ...
    def __lshift__(self, other: int) -> UBig: ...
    def __rshift__(self, other: int) -> UBig: ...
    def __and__(self, other: int | UBig | IBig) -> UBig: ...
    @overload
    def __or__(self, other: UBig) -> UBig: ...
    @overload
    def __or__(self, other: int | IBig) -> IBig: ...
    @overload
    def __xor__(self, other: UBig) -> UBig: ...
    @overload
    def __xor__(self, other: int | IBig) -> IBig: ...

class IBig:
    def __init__(self, obj: int | str): ...

class FBig: ...
class DBig: ...
class RBig: ...
